<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="x-ua-compatible" content="ie=edge"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="generator" content="Gatsby 2.19.22"><style data-emotion-css="g7xa0w 1j6w1lk 9qmntt c2xsu4 12w9zwq 1cbm364 v7zun1 2t3cv3 j6og6x 1ulrd38 177nb4l 1c714c 1u2ngy8 n2wq6l 1okje3k 1r5spv3 guslj3 hyqbg3 1qmy2f9 acwcvw ifr8pt 1suwglb 15nrm4w i8dtig k4yeou 1wfhlg8 1i892k8 17lr4dl wtmayu 8ro7e7 1baulvz j9xfyi owp70s 13pzad3 bonhtd 16cdh0w kvr7so 1lxuut8 go1izf 1n2mv2k 1xwrxje uv7gtw wsl0jz 1dpmz2r lrw0vs 1yv4na5 1lejymi 1ywl6lu 1rb2pi7 13xgcyn x5abi1 loprnw oruwol 1kr4fmq 1ikmn1h uirvwh 1bkjloc 1qfjwci 1mwaxro 1nki19k 1bp8pg5 1icj3s9 1e2dtck h7w5cw 1stoowq 1r7n2xc 91fkl8 1wxzomg 19dss5w no5qqa 1ob3nm1 1jk781r 1u6f325 t1e4o7 1ty11oc 1r5ct1h 1rr4qq7 1k376o7 jgo1yj 148vr0x rr0t5o 1o5ko6q 182uhlb">:root{--c-primary:#15aabf;--c-muted:#717a82;--c-light:#f1f3f5;--c-dark:#495057;--c-text:#343a40;--c-background:#f8f9fa;--c-border:#dee2e6}::selection{background-color:rgba(21,170,191,.6);color:#fff;text-shadow:0 0 .25rem rgba(0,0,0,.4)}*,:after,:before{box-sizing:border-box}body{margin:0;color:#343a40;background-color:#f8f9fa;font-size:1rem;font-family:system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;font-weight:400;line-height:1.5;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}hr{height:1px;margin-top:1rem;margin-bottom:1rem;border:0;color:inherit;background-color:currentColor;opacity:.2}figure{margin:0;margin-bottom:1rem}strong{font-weight:700}small{font-size:80%}svg{vertical-align:text-bottom}h1{margin:0;margin-bottom:1rem;line-height:1.2;font-weight:500;font-size:2.25rem}h2{margin:0;margin-bottom:1rem;line-height:1.2;font-weight:500;font-size:1.875rem}h3{margin:0;margin-bottom:1rem;line-height:1.2;font-weight:500;font-size:1.5rem}h4{margin:0;margin-bottom:1rem;line-height:1.2;font-weight:500;font-size:1.25rem}h5{margin:0;margin-bottom:1rem;line-height:1.2;font-weight:500;font-size:1.125rem}h6{margin:0;margin-bottom:1rem;line-height:1.2;font-weight:500;font-size:1rem}p{margin:0;margin-bottom:1rem}p:last-child{margin-bottom:0}blockquote{margin:0;margin-bottom:1rem;padding:1rem;border-left:8px solid #dee2e6;border-color:#20cee7;border-radius:.25rem;background-color:#f1f3f5}dl,ol,ul{margin:0;margin-bottom:1rem}ol,ul{padding-left:2rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}img{max-width:100%}a{color:#15aabf;-webkit-text-decoration:none;text-decoration:none}a:hover{color:#1296a8;-webkit-text-decoration:underline;text-decoration:underline}a:active{color:#108191}pre{margin:0;margin-bottom:1rem}pre code{display:block;overflow:auto;padding-left:1rem;padding-right:1rem;padding-top:1rem;padding-bottom:1rem;border-radius:.25rem;line-height:inherit;word-wrap:normal;word-break:normal}pre .cdata,pre .comment,pre .doctype,pre .prolog{color:#708090}pre .punctuation{color:#f8f8f2}pre .namespace{opacity:.7}pre .constant,pre .deleted,pre .property,pre .symbol,pre .tag{color:#f92672}pre .boolean,pre .number{color:#ae81ff}pre .attr-name,pre .builtin,pre .char,pre .inserted,pre .selector,pre .string{color:#a6e22e}pre .entity,pre .language-css .string,pre .operator,pre .style .string,pre .url,pre .variable{color:#f8f8f2}pre .atrule,pre .attr-value,pre .class-name,pre .function{color:#e6db74}pre .keyword{color:#66d9ef}pre .important,pre .regex{color:#fd971f}pre .bold,pre .important{font-weight:600}pre .italic{font-style:italic}pre .entity{cursor:help}code{padding-left:.25rem;padding-right:.25rem;padding-top:.125rem;padding-bottom:.125rem;border-radius:.1875rem;background-color:#272822;color:#f8f8f2;font-family:"Fira Code",Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:87.5%;line-height:1.125}table{margin:0;margin-bottom:1rem;display:block;overflow:auto;width:100%;border-collapse:collapse;border-spacing:0}td,th{padding-left:1rem;padding-right:1rem;padding-top:.5rem;padding-bottom:.5rem;text-align:left;border:1px solid #dee2e6}th{font-weight:600}textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;overflow:auto;resize:vertical}.css-1j6w1lk{position:absolute;overrflow:hidden;height:1px;width:1px;margin:-.25rem;padding:0;top:-999px;-webkit-clip:rect(0 0 0 0);clip:rect(0 0 0 0)}.css-1j6w1lk:focus{position:fixed;z-index:99;top:0;left:0;width:auto;height:auto;margin:.5rem;padding:1rem;font-weight:600;background-color:#f8f9fa;-webkit-clip:auto;clip:auto}.css-9qmntt:before{display:block;content:"";height:3rem}.css-c2xsu4{position:fixed;top:0;z-index:30;width:100%;border-bottom:1px solid #dee2e6;background-color:#f8f9fa;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0);-webkit-transition:-webkit-transform .3s linear;-webkit-transition:transform .3s linear;transition:transform .3s linear;will-change:transform}.css-12w9zwq{max-width:75rem;margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:3rem}.css-1cbm364{color:currentColor;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding-left:.25rem;padding-right:.25rem;font-size:1.25rem}.css-1cbm364:hover{-webkit-text-decoration:none;text-decoration:none}.css-1cbm364:hover{-webkit-text-decoration:none;text-decoration:none}.css-v7zun1{width:25px;height:25px;margin-right:.5rem}.css-2t3cv3{fill:#15aabf}.css-j6og6x{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;overflow-x:auto;-webkit-flex:1;-ms-flex:1;flex:1;margin-bottom:0;margin-left:.25rem;margin-right:.25rem;padding-left:.25rem;padding-right:.25rem;list-style:none;white-space:nowrap;-webkit-mask-image:linear-gradient(to right,rgba(0,0,0,0),#000 1em,#000 93%,rgba(0,0,0,0));mask-image:linear-gradient(to right,rgba(0,0,0,0),#000 1em,#000 93%,rgba(0,0,0,0));-webkit-overflow-scrolling:touch;-ms-overflow-scrolling:touch;-ms-overflow-style:none}@media screen and (min-width:640px){.css-j6og6x{margin-left:1rem;margin-right:1rem;-webkit-mask-image:none;mask-image:none}}.css-j6og6x::-webkit-scrollbar{display:none}.css-1ulrd38{color:currentColor;display:block;opacity:.9;padding:.5rem}.css-1ulrd38:hover{-webkit-text-decoration:none;text-decoration:none}.css-1ulrd38:hover{-webkit-text-decoration:none;text-decoration:none}.css-177nb4l{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-block;margin:0;padding-left:.5rem;padding-right:.5rem;padding-top:.5rem;padding-bottom:.5rem;border:1px solid #dee2e6;border-color:transparent;border-radius:.25rem;background-color:transparent;color:#fff;font-size:1rem;font-weight:600;line-height:1;text-align:center;-webkit-text-decoration:none;text-decoration:none;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:border .3s,background .3s,color .3s,box-shadow .3s;transition:border .3s,background .3s,color .3s,box-shadow .3s;color:#717a82;-webkit-transform:scale(.75);-ms-transform:scale(.75);transform:scale(.75)}.css-177nb4l:hover{border-color:transparent;background-color:transparent;color:#fff;-webkit-text-decoration:none;text-decoration:none}.css-177nb4l:active{border-color:transparent;background-color:transparent;color:#fff}.css-177nb4l:focus{box-shadow:0 0 0 .2rem rgba(21,170,191,.2);outline:0}.css-177nb4l:disabled{opacity:.5;cursor:default}.css-177nb4l:hover{color:#717a82}.css-1c714c{display:block;overflow:hidden;position:relative;width:24px;height:24px;border-radius:50%;border:0;box-shadow:inset 8px -8px 0 0 currentColor;background-color:transparent;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-webkit-transition:border .3s,box-shadow .3s,background .3s,-webkit-transform .3s;-webkit-transition:border .3s,box-shadow .3s,background .3s,transform .3s;transition:border .3s,box-shadow .3s,background .3s,transform .3s;will-change:transform}.css-1c714c:before{position:absolute;right:-9px;top:-9px;width:24px;height:24px;border:0;border-radius:50%;content:"";opacity:1;-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0);-webkit-transition:border .3s,opacity .3s,-webkit-transform .3s;-webkit-transition:border .3s,opacity .3s,transform .3s;transition:border .3s,opacity .3s,transform .3s;will-change:transform}.css-1c714c:after{position:absolute;top:50%;left:50%;margin:-4px 0 0 -4px;border-radius:50%;width:8px;height:8px;content:"";box-shadow:0 -23px 0 currentColor,0 23px 0 currentColor,23px 0 0 currentColor,-23px 0 0 currentColor,15px 15px 0 currentColor,-15px 15px 0 currentColor,15px -15px 0 currentColor,-15px -15px 0 currentColor;-webkit-transform:scale(0);-ms-transform:scale(0);transform:scale(0);-webkit-transition:-webkit-transform .3s;-webkit-transition:transform .3s;transition:transform .3s;will-change:transform}.css-1u2ngy8{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:75rem;margin-left:auto;margin-right:auto}.css-n2wq6l{color:currentColor}.css-n2wq6l:hover{-webkit-text-decoration:none;text-decoration:none}.css-1okje3k{padding-top:3rem;padding-bottom:3rem;border-top:1px solid #dee2e6;background-color:#f8f9fa;color:#717a82;font-size:.875rem;text-align:center}@media screen and (min-width:640px){.css-1okje3k{text-align:left}}.css-1r5spv3{max-width:75rem;margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem}.css-guslj3{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-left:-1rem;margin-right:-1rem}.css-hyqbg3{width:100%;margin-bottom:1.5rem;padding-left:1rem;padding-right:1rem}@media screen and (min-width:1024px){.css-hyqbg3{width:45%}}.css-1qmy2f9{font-weight:300;margin-bottom:.5rem}.css-acwcvw{margin-bottom:1rem}.css-ifr8pt{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem}.css-1suwglb{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-block;margin:0;padding-left:1rem;padding-right:1rem;padding-top:.5rem;padding-bottom:.5rem;border:1px solid #dee2e6;border-radius:.25rem;background-color:transparent;color:#343a40;line-height:inherit;font-size:1rem;-webkit-transition:border .3s,background .3s,color .3s,box-shadow .3s;transition:border .3s,background .3s,color .3s,box-shadow .3s;-webkit-flex:1;-ms-flex:1;flex:1;border-top-right-radius:0;border-bottom-right-radius:0}.css-1suwglb:focus{box-shadow:0 0 0 .2rem rgba(21,170,191,.2);border-color:#15aabf;outline:0}.css-1suwglb:disabled{opacity:.5;cursor:default}.css-15nrm4w{-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-block;margin:0;padding-left:.5rem;padding-right:.5rem;padding-top:.5rem;padding-bottom:.5rem;border:1px solid #dee2e6;border-color:#dee2e6;border-radius:.25rem;background-color:transparent;color:#dee2e6;font-size:1rem;font-weight:600;line-height:1;text-align:center;-webkit-text-decoration:none;text-decoration:none;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:border .3s,background .3s,color .3s,box-shadow .3s;transition:border .3s,background .3s,color .3s,box-shadow .3s;padding-left:1rem;padding-right:1rem;border-left:0;border-top-left-radius:0;border-bottom-left-radius:0;color:currentColor}.css-15nrm4w:hover{border-color:#cfd5db;background-color:#cfd5db;color:#495057;-webkit-text-decoration:none;text-decoration:none}.css-15nrm4w:active{border-color:#b2bcc5;background-color:#b2bcc5;color:#495057}.css-15nrm4w:focus{box-shadow:0 0 0 .2rem rgba(21,170,191,.2);outline:0}.css-15nrm4w:disabled{opacity:.5;cursor:default}.css-i8dtig{margin-left:-.25rem;margin-right:-.25rem;padding-left:0;list-style:none}.css-k4yeou{display:inline-block;margin-left:.25rem;margin-right:.25rem;margin-bottom:.5rem}.css-1wfhlg8{color:currentColor;-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-block;margin:0;padding-left:.5rem;padding-right:.5rem;padding-top:.5rem;padding-bottom:.5rem;border:1px solid #dee2e6;border-color:#dee2e6;border-radius:.25rem;background-color:transparent;color:#dee2e6;font-size:1rem;font-weight:600;line-height:1;text-align:center;-webkit-text-decoration:none;text-decoration:none;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:border .3s,background .3s,color .3s,box-shadow .3s;transition:border .3s,background .3s,color .3s,box-shadow .3s;color:currentColor}.css-1wfhlg8:hover{-webkit-text-decoration:none;text-decoration:none}.css-1wfhlg8:hover{border-color:#cfd5db;background-color:#cfd5db;color:#495057;-webkit-text-decoration:none;text-decoration:none}.css-1wfhlg8:active{border-color:#b2bcc5;background-color:#b2bcc5;color:#495057}.css-1wfhlg8:focus{box-shadow:0 0 0 .2rem rgba(21,170,191,.2);outline:0}.css-1wfhlg8:disabled{opacity:.5;cursor:default}.css-1i892k8{width:100%;margin-bottom:1.5rem;padding-left:1rem;padding-right:1rem}@media screen and (min-width:768px){.css-1i892k8{width:55%}}@media screen and (min-width:1024px){.css-1i892k8{width:25%}}.css-17lr4dl{padding-left:0;list-style:none;line-height:1.75}.css-wtmayu{display:inline-block;margin-right:.25rem}.css-wtmayu:after{content:"\002C"}.css-8ro7e7{color:currentColor}.css-8ro7e7:hover{-webkit-text-decoration:none;text-decoration:none}.css-8ro7e7:before{content:"\0023"}.css-1baulvz{display:inline-block}.css-j9xfyi{width:100%;margin-bottom:1.5rem;padding-left:1rem;padding-right:1rem}@media screen and (min-width:640px){.css-j9xfyi{width:50%}}@media screen and (min-width:768px){.css-j9xfyi{width:25%}}@media screen and (min-width:1024px){.css-j9xfyi{width:15%}}.css-owp70s{padding-left:.25rem;padding-right:.25rem;list-style:none}.css-13pzad3:before{content:"\279F";margin-right:.25rem;opacity:.7}.css-bonhtd{width:100%;margin-bottom:1.5rem;padding-left:1rem;padding-right:1rem}@media screen and (min-width:640px){.css-bonhtd{width:50%}}@media screen and (min-width:768px){.css-bonhtd{width:20%}}@media screen and (min-width:1024px){.css-bonhtd{width:15%}}.css-16cdh0w{display:block!important;margin-left:auto;margin-right:auto}.css-kvr7so{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-top:1rem;border-top:1px solid #dee2e6}@media screen and (min-width:640px){.css-kvr7so{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row}}.css-1lxuut8{-webkit-flex:1;-ms-flex:1;flex:1;margin-bottom:0;margin-left:.5rem;padding-left:0}.css-go1izf{display:inline;margin-right:.5rem}.css-1n2mv2k{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.css-1xwrxje{color:currentColor;margin-right:.25rem}.css-1xwrxje:hover{-webkit-text-decoration:none;text-decoration:none}.css-uv7gtw{margin-left:.25rem}.css-wsl0jz{color:currentColor;margin-left:.25rem}.css-wsl0jz:hover{-webkit-text-decoration:none;text-decoration:none}.css-1dpmz2r{position:absolute!important;top:0;z-index:-1;width:100%;min-height:40rem;max-height:100vh;background-color:#495057}.css-1dpmz2r:after,.css-1dpmz2r:before{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.css-1dpmz2r:before{background:0/4px url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 2' stroke='%23000' stroke-linecap='square' stroke-width='0.5'%3E%3Cline x1='0' y1='1' x2='1' y2='0'/%3E%3Cline x1='1' y1='2' x2='2' y2='1'/%3E%3C/svg%3E");opacity:.6}.css-1dpmz2r:after{background:linear-gradient(transparent 45%,#f8f9fa)}.css-1dpmz2r img{-webkit-filter:blur(5rem);filter:blur(5rem);-webkit-transform:translateZ(0) scale(1.1);-ms-transform:translateZ(0) scale(1.1);transform:translateZ(0) scale(1.1)}.css-lrw0vs{max-width:75rem;margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem;margin-bottom:2rem}.css-1yv4na5{padding-top:10vw;padding-bottom:10vw;text-align:center;color:#fff;font-size:1.25rem;text-shadow:0 0 .25rem rgba(0,0,0,.4);padding-top:6vw;padding-bottom:4vw}.css-1lejymi{text-transform:uppercase}.css-1ywl6lu:before{display:inline-block;margin-left:.5rem;margin-right:.5rem;content:"\002f";opacity:.6}.css-1rb2pi7{font-size:2.25rem;line-height:1.5}@media screen and (min-width:640px){.css-1rb2pi7{font-size:3rem}}.css-13xgcyn{margin-left:-1rem;margin-right:-1rem;overflow:visible!important;background-color:#495057}@media screen and (min-width:640px){.css-13xgcyn{margin-left:0;margin-right:0}}.css-13xgcyn:after,.css-13xgcyn:before{display:none;position:absolute;top:10%;z-index:-1;width:1rem;height:120%;background:rgba(0,0,0,.2);content:"";-webkit-filter:blur(1rem);filter:blur(1rem)}@media screen and (min-width:640px){.css-13xgcyn:after,.css-13xgcyn:before{display:block}}.css-13xgcyn:before{left:-.5rem;-webkit-transform:rotate(-1deg);-ms-transform:rotate(-1deg);transform:rotate(-1deg)}.css-13xgcyn:after{right:-.5rem;-webkit-transform:rotate(1deg);-ms-transform:rotate(1deg);transform:rotate(1deg)}.css-x5abi1{margin-left:-1rem;margin-right:-1rem;padding-left:5%;padding-right:5%;padding-top:4%;padding-bottom:4%;min-height:80vh;background-color:#f8f9fa;font-size:calc(100% + .1vw);line-height:2;word-wrap:break-word}@media screen and (min-width:640px){.css-x5abi1{margin-left:0;margin-right:0;padding-left:10%;padding-right:10%;padding-top:6%;padding-bottom:6%}}.css-x5abi1 h1,.css-x5abi1 h2,.css-x5abi1 h3,.css-x5abi1 h4,.css-x5abi1 h5,.css-x5abi1 h6{margin:1.4em 0 .8em}.css-x5abi1 .gatsby-resp-image-wrapper{margin-top:5%;margin-bottom:5%;max-width:860px!important}.css-x5abi1 .footnotes p{display:inline}.css-loprnw{margin-left:auto;margin-right:auto;padding-top:3vw;padding-bottom:3vw;max-width:50rem}.css-oruwol{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:1rem;padding-top:.5rem;padding-bottom:.5rem;border-bottom:1px solid #dee2e6;color:#717a82;font-size:.875rem}.css-1kr4fmq{margin-right:1rem}.css-1ikmn1h{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-left:auto}.css-1ikmn1h span{margin-right:.25rem}.css-1ikmn1h a{margin-left:.25rem}.css-uirvwh{margin-bottom:3rem}.css-1bkjloc{position:absolute;overflow:hidden;-webkit-clip:rect(0,0,0,0);clip:rect(0,0,0,0);padding:0;width:1px;height:1px;border:0;white-space:nowrap}.css-1qfjwci{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;padding-top:1.5rem;padding-bottom:1.5rem}.css-1mwaxro{border-radius:50%;background-color:#fff;margin-right:1rem;width:96px;height:96px;box-shadow:0 .125rem .25rem rgba(0,0,0,.2)}.css-1nki19k{-webkit-flex:1 1 6rem;-ms-flex:1 1 6rem;flex:1 1 6rem}.css-1bp8pg5{color:currentColor;-webkit-appearance:none;-moz-appearance:none;appearance:none;display:inline-block;margin:0;padding-left:1rem;padding-right:1rem;padding-top:.5rem;padding-bottom:.5rem;border:1px solid #dee2e6;border-color:transparent;border-radius:.25rem;background-color:transparent;color:#15aabf;font-size:1rem;font-weight:600;line-height:inherit;text-align:center;-webkit-text-decoration:none;text-decoration:none;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:border .3s,background .3s,color .3s,box-shadow .3s;transition:border .3s,background .3s,color .3s,box-shadow .3s}.css-1bp8pg5:hover{-webkit-text-decoration:none;text-decoration:none}.css-1bp8pg5:hover{border-color:#1296a8;background-color:#1296a8;color:#fff;-webkit-text-decoration:none;text-decoration:none}.css-1bp8pg5:active{border-color:#0d6d7a;background-color:#0d6d7a;color:#fff}.css-1bp8pg5:focus{box-shadow:0 0 0 .2rem rgba(21,170,191,.2);outline:0}.css-1bp8pg5:disabled{opacity:.5;cursor:default}.css-1icj3s9{margin-bottom:3rem;text-align:center}.css-1e2dtck{fill:#f8f9fa}.css-h7w5cw{margin-top:.5rem;color:#717a82;font-style:italic;font-family:Georgia,Cambria,"Times New Roman",Times,serif}.css-1stoowq{padding-top:2.5rem;background-color:#f1f3f5}.css-1r7n2xc{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;overflow:hidden;-webkit-flex:1 1;-ms-flex:1 1;flex:1 1;-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin-left:1rem;margin-right:1rem;margin-bottom:2.5rem;padding:2rem;border-radius:.25rem;background-color:#495057;color:#fff;box-shadow:0 .125rem .25rem rgba(0,0,0,.2);text-align:center}@media screen and (min-width:1024px){.css-1r7n2xc{-webkit-flex-basis:20rem;-ms-flex-preferred-size:20rem;flex-basis:20rem}}.css-1r7n2xc a{-webkit-text-decoration:none;text-decoration:none}.css-91fkl8{color:rgba(255,255,255,.5)}.css-91fkl8:after,.css-91fkl8:before{display:inline-block;margin-left:.5rem;margin-right:.5rem;content:"\2014\2014";color:rgba(255,255,255,.25)}.css-1wxzomg{padding:.5rem;font-weight:300}.css-19dss5w{-webkit-flex:1;-ms-flex:1;flex:1;margin:1rem;padding-left:0;list-style:none}.css-no5qqa{padding:1rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.css-no5qqa:not(:last-child){border-bottom:1px solid #dee2e6;border-color:rgba(255,255,255,.1)}.css-1ob3nm1{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;overflow:hidden;-webkit-flex:1 1 20rem;-ms-flex:1 1 20rem;flex:1 1 20rem;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;margin-left:1rem;margin-right:1rem;margin-bottom:2.5rem;border-radius:.25rem;background-color:#f8f9fa;box-shadow:0 .125rem .25rem rgba(0,0,0,.2);-webkit-transition:box-shadow .3s,-webkit-transform .3s;-webkit-transition:box-shadow .3s,transform .3s;transition:box-shadow .3s,transform .3s;will-change:transform}.css-1ob3nm1:hover{box-shadow:0 .25rem .5rem rgba(0,0,0,.2);-webkit-transform:translate(0,-2px);-ms-transform:translate(0,-2px);transform:translate(0,-2px)}.css-1jk781r{color:currentColor;position:absolute;top:0;right:0;bottom:0;left:0;z-index:1}.css-1jk781r:hover{-webkit-text-decoration:none;text-decoration:none}.css-1u6f325{max-height:25rem;background-color:#495057;object-fit:cover}.css-t1e4o7{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-flex:1;-ms-flex:1;flex:1;padding:1rem}.css-1ty11oc{color:#717a82;text-transform:uppercase}.css-1r5ct1h{overflow:hidden;font-size:1.5rem;text-overflow:ellipsis;white-space:nowrap}.css-1rr4qq7{-webkit-flex:1;-ms-flex:1;flex:1}.css-1k376o7{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;color:#717a82}.css-jgo1yj{z-index:2;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;margin-bottom:0;padding-left:0;list-style:none}.css-jgo1yj:hover li{margin-left:0}.css-148vr0x{z-index:1;margin-left:0;-webkit-transition:margin .2s;transition:margin .2s}.css-rr0t5o{border-radius:50%;background-color:#fff;width:30px;height:30px;border:1px solid #dee2e6;vertical-align:middle}.css-1o5ko6q{display:inline;margin-bottom:0;margin-left:.25rem;padding-left:0;list-style:none}.css-182uhlb{display:inline}.css-182uhlb:not(:last-child){margin-right:.25rem}.css-182uhlb:not(:last-child):after{content:"\002c"}</style><link rel="sitemap" type="application/xml" href="/sitemap.xml"><title data-react-helmet="true">前端工程化 - 概述 - 汪磊的个人网站</title><link data-react-helmet="true" rel="canonical" href="https://blog.zce.me/2019/08/frontend-engineering-summary/"><link data-react-helmet="true" rel="prev" href="https://blog.zce.me/2019/08/electron-desktop-app/"><link data-react-helmet="true" rel="next" href="https://blog.zce.me/2019/08/frontend-engineering-scaffolding/"><meta data-react-helmet="true" name="og:url" content="https://blog.zce.me/2019/08/frontend-engineering-summary/"><meta data-react-helmet="true" name="description" content="前端工程化是指遵循一定的标准和规范，通过工具提高开发效率、降低维护成本的一种手段。近些年被广泛的关注和探讨，究其原因，主要是因为前端应用的功能要求不断提高，业务逻辑日益复杂。 作为当下互联网时代唯一不可或缺的技术，前端占据了整个开发行业的「半壁江山」。从传统的网站到现在的 H5、移动 App、桌面应用以及小程序，前端…"><meta data-react-helmet="true" name="keywords" content="博客,学习,课程,个人主页,汪磊,zce.me,zce"><meta data-react-helmet="true" name="author" content="汪磊"><meta data-react-helmet="true" name="og:site_name" content="Lei’s"><meta data-react-helmet="true" name="og:title" content="前端工程化 - 概述 - 汪磊的个人网站"><meta data-react-helmet="true" name="og:description" content="前端工程化是指遵循一定的标准和规范，通过工具提高开发效率、降低维护成本的一种手段。近些年被广泛的关注和探讨，究其原因，主要是因为前端应用的功能要求不断提高，业务逻辑日益复杂。 作为当下互联网时代唯一不可或缺的技术，前端占据了整个开发行业的「半壁江山」。从传统的网站到现在的 H5、移动 App、桌面应用以及小程序，前端…"><meta data-react-helmet="true" name="og:type" content="article"><meta data-react-helmet="true" name="og:image" content="https://blog.zce.me/static/85cf3386073e83658ff9334ee0e9976b/14b42/cover.jpg"><meta data-react-helmet="true" name="og:image:width" content="800"><meta data-react-helmet="true" name="og:image:height" content="533"><link rel="icon" href="/icons/icon-48x48.png?v=a99e619d999a8bb8f0f5bee2fa578242"><link rel="manifest" href="/manifest.webmanifest" crossorigin="use-credentials"><meta name="theme-color" content="#339af0"><link rel="apple-touch-icon" sizes="48x48" href="/icons/icon-48x48.png?v=a99e619d999a8bb8f0f5bee2fa578242"><link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png?v=a99e619d999a8bb8f0f5bee2fa578242"><link rel="apple-touch-icon" sizes="96x96" href="/icons/icon-96x96.png?v=a99e619d999a8bb8f0f5bee2fa578242"><link rel="apple-touch-icon" sizes="144x144" href="/icons/icon-144x144.png?v=a99e619d999a8bb8f0f5bee2fa578242"><link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192x192.png?v=a99e619d999a8bb8f0f5bee2fa578242"><link rel="apple-touch-icon" sizes="256x256" href="/icons/icon-256x256.png?v=a99e619d999a8bb8f0f5bee2fa578242"><link rel="apple-touch-icon" sizes="384x384" href="/icons/icon-384x384.png?v=a99e619d999a8bb8f0f5bee2fa578242"><link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512x512.png?v=a99e619d999a8bb8f0f5bee2fa578242"><style>.anchor.before{position:absolute;top:0;left:0;transform:translateX(-100%);padding-right:4px}.anchor.after{display:inline-block;padding-left:4px}h1 .anchor svg,h2 .anchor svg,h3 .anchor svg,h4 .anchor svg,h5 .anchor svg,h6 .anchor svg{visibility:hidden}h1 .anchor:focus svg,h1:hover .anchor svg,h2 .anchor:focus svg,h2:hover .anchor svg,h3 .anchor:focus svg,h3:hover .anchor svg,h4 .anchor:focus svg,h4:hover .anchor svg,h5 .anchor:focus svg,h5:hover .anchor svg,h6 .anchor:focus svg,h6:hover .anchor svg{visibility:visible}</style><script>document.addEventListener("DOMContentLoaded",function(e){var o=window.decodeURI(location.hash.replace("#",""));if(""!==o){var n=document.getElementById(o);if(n){var t=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop,d=document.documentElement.clientTop||document.body.clientTop||0,c=n.getBoundingClientRect().top+t-d;setTimeout(function(){window.scrollTo(0,c)},0)}}})</script><link as="script" rel="preload" href="/c89e15.js"><link as="script" rel="preload" href="/d32c95.js"><link as="script" rel="preload" href="/cdf4f2.js"><link as="script" rel="preload" href="/aa327c.js"><link as="fetch" rel="preload" href="/page-data\2019\08\frontend-engineering-summary\page-data.json" crossorigin="anonymous"><link as="fetch" rel="preload" href="/page-data\app-data.json" crossorigin="anonymous"></head><body style="opacity:0;background:#35363a;transition:opacity .5s"><div id="___gatsby"><div style="outline:0" tabindex="-1" id="gatsby-focus-wrapper"><a href="#content" class="css-1j6w1lk">跳转到内容区</a><header class="css-9qmntt"><nav aria-label="主要导航" class="css-c2xsu4"><div class="css-12w9zwq"><a aria-label="回到首页" class="css-1cbm364" href="/"><svg viewBox="0 0 472 450" aria-hidden="true" class="css-v7zun1"><defs><filter id="shadow" x="-12.7%" y="-13.4%" width="125.4%" height="126.7%" filterUnits="objectBoundingBox"><feOffset in="SourceAlpha" result="offset-outer"></feOffset><feGaussianBlur stdDeviation="20" in="offset-outer" result="blue-outer"></feGaussianBlur><feComposite in="blue-outer" in2="SourceAlpha" operator="out" result="blue-outer"></feComposite><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" in="blue-outer"></feColorMatrix></filter></defs><mask id="mask" fill="#fff"><path d="M472 114.26L203.029 335.74H407.1L472 449.48H64.9L0 335.74l268.971-221.48H64.9L0 .52h407.1z"></path></mask><g mask="url(#mask)" class="css-2t3cv3"><path d="M0 0h472v449H0z"></path></g><g mask="url(#mask)"><path d="M0 335.74l64.9 113.74L472 114.26 407.1.52z" filter="url(#shadow)"></path></g></svg><span>Lei’s</span></a><ul class="css-j6og6x"><li><a class="css-1ulrd38" href="/">首页</a></li><li><a class="css-1ulrd38" href="/courses/">课程</a></li><li><a class="css-1ulrd38" href="/blog/">博客</a></li><li><a class="css-1ulrd38" href="/about/">关于</a></li><li><a class="css-1ulrd38" href="/contact/">联系</a></li><li><a class="css-1ulrd38" href="/discuss/">讨论</a></li></ul><button title="切换至「暗色」模式" aria-label="切换至「暗色」模式" class="css-177nb4l"><span class="css-1c714c"></span></button></div></nav></header><main id="content"><div class="css-1dpmz2r gatsby-image-wrapper" style="position:relative;overflow:hidden"><div aria-hidden="true" style="width:100%;padding-bottom:66.66666666666667%"></div><img aria-hidden="true" src="" alt="" style="position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition-delay:.5s"><noscript><picture><source srcset="/static/a159248328406e0a7886925b2974ac78/c158a/cover.jpg 270w, /static/a159248328406e0a7886925b2974ac78/083fb/cover.jpg 540w, /static/a159248328406e0a7886925b2974ac78/c9315/cover.jpg 766w" sizes="(max-width: 766px) 100vw, 766px"><img loading="lazy" sizes="(max-width: 766px) 100vw, 766px" srcset="/static/a159248328406e0a7886925b2974ac78/c158a/cover.jpg 270w, /static/a159248328406e0a7886925b2974ac78/083fb/cover.jpg 540w, /static/a159248328406e0a7886925b2974ac78/c9315/cover.jpg 766w" src="/static/a159248328406e0a7886925b2974ac78/c9315/cover.jpg" alt="" style="position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center"></picture></noscript></div><article role="main" class="css-lrw0vs"><header class="css-1yv4na5"><span class="css-1lejymi"><time datetime="2019-08-20T19:32:30.000Z" title="2019-08-20T19:32:30.000Z" aria-label="发表于">2019年8月20日</time><span role="separator" aria-hidden="true" class="css-1ywl6lu"></span><a aria-label="发表在" class="css-n2wq6l" href="/categories/tutorial/">教程</a></span><h1 class="css-1rb2pi7">前端工程化 - 概述</h1></header><div class="css-13xgcyn gatsby-image-wrapper" style="position:relative;overflow:hidden"><div aria-hidden="true" style="width:100%;padding-bottom:66.66666666666667%"></div><img aria-hidden="true" src="" title="前端工程化 - 概述" alt="前端工程化 - 概述" style="position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition-delay:.5s"><noscript><picture><source srcset="/static/a159248328406e0a7886925b2974ac78/c158a/cover.jpg 270w, /static/a159248328406e0a7886925b2974ac78/083fb/cover.jpg 540w, /static/a159248328406e0a7886925b2974ac78/c9315/cover.jpg 766w" sizes="(max-width: 766px) 100vw, 766px"><img loading="lazy" sizes="(max-width: 766px) 100vw, 766px" srcset="/static/a159248328406e0a7886925b2974ac78/c158a/cover.jpg 270w, /static/a159248328406e0a7886925b2974ac78/083fb/cover.jpg 540w, /static/a159248328406e0a7886925b2974ac78/c9315/cover.jpg 766w" src="/static/a159248328406e0a7886925b2974ac78/c9315/cover.jpg" alt="前端工程化 - 概述" title="前端工程化 - 概述" style="position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center"></picture></noscript></div><section class="css-x5abi1"><p>前端工程化是指遵循一定的标准和规范，通过工具提高开发效率、降低维护成本的一种手段。近些年被广泛的关注和探讨，究其原因，主要是因为前端应用的功能要求不断提高，业务逻辑日益复杂。</p><p>作为当下互联网时代唯一不可或缺的技术，前端占据了整个开发行业的「半壁江山」。从传统的网站到现在的 H5、移动 App、桌面应用以及小程序，前端技术几乎无所不能的全面覆盖。</p><p>在这些表象的背后实际上是前端行业对开发人员的技能要求发生了天翻地覆的变化，以往“写 Demo，套模板，调页面”这种刀耕火种的方式已经完全不符合当下对开发效率的要求。前端工程化就是在这样的背景下被提上台面，成为前端工程师必要的手段之一。</p><h3 id="解决的问题" style="position:relative"><a href="#%E8%A7%A3%E5%86%B3%E7%9A%84%E9%97%AE%E9%A2%98" aria-label="解决的问题 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>解决的问题</h3><p>技术是为了解决问题而存在的，前端工程化也不例外，这里我列举一些大家在日常开发过程中经常会面临的一些问题（不仅限于此）：</p><ul><li>想要使用 ES6、ES7 这些新特性，但是兼容有问题</li><li>想要使用 Less / Sass / PostCSS 增强 CSS 的编程性，但是运行环境不能直接支持</li><li>想要使用模块化的方式提高项目的可维护性，同样运行环境不能直接支持</li><li>项目部署上线前需要手动压缩资源文件，过程中需要手动上传代码到服务器，还容易出错</li><li>多人协作开发，无法硬性统一大家的代码风格</li><li>从仓库中 pull 回来的代码质量无法保证</li><li>部分功能开发时需要等待后端服务接口提前完成</li></ul><p>我们将这些问题归纳、总结为以下这几点：</p><ul><li>传统语言或语法的弊端</li><li>无法使用模块化 / 组件化</li><li>重复的机械式工作</li><li>代码风格、格式无法统一</li><li>仓库代码质量无法保证</li><li>依赖后端服务接口支持</li><li>整体依赖后端项目</li></ul><h3 id="具体表现" style="position:relative"><a href="#%E5%85%B7%E4%BD%93%E8%A1%A8%E7%8E%B0" aria-label="具体表现 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>具体表现</h3><p>接下来，我就以最简单的项目开发流程为例，看看前端工程化在这个过程的表现，让大家先从整体角度对前端工程化有一个全面的认识。</p><p>从项目的创建、到编码、再到预览、再到提交、最后到部署，每一个环节我们都可以通过工程化的方式大大提到工作效率，具体来说就是：</p><ol><li>创建项目过程我们可以使用脚手架工具自动完成；</li><li>编码过程我们可以通过编译或者转化工具提前使用一些新特性，利用格式化和代码检查工具自动检测和修复代码中的基础问题；</li><li>预览时再通过 Web Server 自动预览并享受热更新的体验，并且可以使用 Mock 的方式在后端服务接口未完成的情况下，直接开发具体的业务功能；</li><li>到了代码提交环节，我们可以使用 Git Hook 自动化的在提交之前做出项目检查，确保不会提交有问题的代码，甚至连提交的日志都可以严格限制格式；</li><li>最后在部署阶段，我可以使用一行命令代替传统手动的 FTP 上传，甚至还可以实现在代码提交过后自动部署到服务器；</li></ol><h3 id="工程化-≠-工具" style="position:relative"><a href="#%E5%B7%A5%E7%A8%8B%E5%8C%96-%E2%89%A0-%E5%B7%A5%E5%85%B7" aria-label="工程化 ≠ 工具 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>工程化 ≠ 工具</h3><p>现阶段由于部分工具的「过于强大」，例如 Webpack，很多新手误认为工程化就是 Webpack，有了 Webpack 就是有了工程化。其实不然，工具并非工程化的核心，工程化的核心应该是对项目的一种规划或者架构，工具只是落地实现的手段。</p><p>以一个普通项目为例，落实工程化的第一件事是规划整体项目的工作流架构，包括：</p><ol><li>文件的组织结构</li><li>源代码的开发范式</li><li>语言或者语法规范</li><li>前后端分离方式</li><li>其他对开发阶段的需求</li></ol><p>有了整体的规划过后，再来具体考虑选择搭配使用哪些具体的工具，配置具体的选项。这才是一个工程化的过程。</p><p>当然你也可以从一些集成式的工程化方案中找到思路，例如：</p><ul><li>create-react-app</li><li>vue-cli</li><li>angular-cli</li></ul><p>可能很多人会认为这些就是脚手架工具，其实不然，不同于之前提到的工具，这些应该属于特定类型的项目中官方给出的集成式工程化方案。就拿 vue-cli 来说，创建项目、约定项目结构、提供开发服务、编译、Lint，这些都是集成在其中的。</p><h3 id="厥功至伟的-nodejs" style="position:relative"><a href="#%E5%8E%A5%E5%8A%9F%E8%87%B3%E4%BC%9F%E7%9A%84-nodejs" aria-label="厥功至伟的 nodejs permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>厥功至伟的 Node.js</h3><p>当然这一切都归功于 Node.js，如果说 AJAX 给前端带来了新的生命力，那么 Node.js 对于前端而言，除了让 JavaScript 有了新的舞台，它还给整个前端行业带来了一次「工业革命」，可以毫不夸张的说没有 Node.js 就没有今天的前端。</p><p>接下来的很长一段时间中，我们用到的工具几乎都是使用 Node.js 开发的，所以说前端工程化由 Node.js 强力驱动。</p><h3 id="总结" style="position:relative"><a href="#%E6%80%BB%E7%BB%93" aria-label="总结 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>总结</h3><p>当然工程化在我看来是一个非常庞大的概念，也一直在不断成长的过程中，值得强调的是：不管它如何发展，始终都只是为了解决问题而存在，切莫为了技术而技术。</p><p>接下来我们就通过五个专题具体学习如何在这些维度落实前端工程化。</p></section><footer class="css-loprnw"><section class="css-oruwol"><div title="更新于" aria-label="更新于" class="css-1kr4fmq"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20h9"></path><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path></svg><time datetime="2020-02-09T10:46:45.746Z" title="2020-02-09T10:46:45.746Z" class="css-uv7gtw">2020年2月9日</time></div><div title="标记为" aria-label="标记为"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"></path><line x1="7" y1="7" x2="7.01" y2="7"></line></svg><ul class="css-1o5ko6q"><li class="css-182uhlb"><a class="css-8ro7e7" href="/tags/工程化/">工程化</a></li></ul></div><div aria-label="分享到" class="css-1ikmn1h"><span>分享到:</span><a title="分享到推特" target="_blank" rel="noopener noreferrer" href="https://twitter.com/share?text=前端工程化 - 概述&amp;url=https://blog.zce.me/2019/08/frontend-engineering-summary/" class="css-n2wq6l"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg></a><a title="分享到脸书" target="_blank" rel="noopener noreferrer" href="https://www.facebook.com/sharer/sharer.php?u=https://blog.zce.me/2019/08/frontend-engineering-summary/" class="css-n2wq6l"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path></svg></a><a title="分享到朋友圈" target="_blank" rel="noopener noreferrer" href="http://qr.topscan.com/api.php?text=https://blog.zce.me/2019/08/frontend-engineering-summary/" class="css-n2wq6l"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><line x1="14.31" y1="8" x2="20.05" y2="17.94"></line><line x1="9.69" y1="8" x2="21.17" y2="8"></line><line x1="7.38" y1="12" x2="13.12" y2="2.06"></line><line x1="9.69" y1="16" x2="3.95" y2="6.06"></line><line x1="14.31" y1="16" x2="2.83" y2="16"></line><line x1="16.62" y1="12" x2="10.88" y2="21.94"></line></svg></a></div></section><section class="css-uirvwh"><h3 class="css-1bkjloc">作者</h3><div class="css-1qfjwci"><img class="css-1mwaxro" alt="汪磊" src="/static/e89ac07ab5eb7c9cf655a5ed73f61806/2179e/avatar-zce.jpg" srcset="/static/e89ac07ab5eb7c9cf655a5ed73f61806/2179e/avatar-zce.jpg, /static/e89ac07ab5eb7c9cf655a5ed73f61806/24010/avatar-zce.jpg 1.5x, /static/e89ac07ab5eb7c9cf655a5ed73f61806/a1582/avatar-zce.jpg 2x" loading="lazy"><div class="css-1nki19k"><h4>汪磊</h4><p>MAKE IT BETTER!</p></div><a class="css-1bp8pg5" href="/authors/zce/">阅读更多</a></div></section><section class="css-1icj3s9"><h3 class="css-1bkjloc">许可</h3><a title="View license" target="_blank" rel="noopener noreferrer" href="https://creativecommons.org/licenses/by-sa/4.0/" class="css-n2wq6l"><svg viewBox="0 0 120 42" width="160" aria-hidden="true"><path fill="currentColor" d="M117.8,0H2.2C1,0,0,1,0,2.2v39.2C0,41.8,0.2,42,0.5,42h119c0.3,0,0.5-0.2,0.5-0.5V2.2C120,1,119,0,117.8,0z M2.2,1h115.5c0.7,0,1.2,0.6,1.2,1.2c0,0,0,15.8,0,27.2H36.4c-3,5.5-8.9,9.2-15.5,9.2c-6.7,0-12.5-3.7-15.5-9.2H1C1,18.1,1,2.2,1,2.2C1,1.6,1.6,1,2.2,1z"></path><path d="M61,32.7c0.3,0,0.6,0,0.9,0.1c0.3,0.1,0.5,0.1,0.7,0.3c0.2,0.1,0.3,0.3,0.4,0.5c0.1,0.2,0.2,0.5,0.2,0.8S63.1,35,63,35.2c-0.2,0.2-0.4,0.4-0.7,0.5c0.4,0.1,0.7,0.3,0.9,0.6s0.3,0.6,0.3,1.1c0,0.3-0.1,0.6-0.2,0.9c-0.1,0.2-0.3,0.4-0.5,0.6c-0.2,0.2-0.5,0.3-0.8,0.3c-0.3,0.1-0.6,0.1-0.9,0.1h-1.2h-2v-6.6L61,32.7L61,32.7z M60.8,35.4c0.3,0,0.5-0.1,0.6-0.2c0.2-0.1,0.3-0.3,0.3-0.6c0-0.2,0-0.3-0.1-0.4c-0.1-0.1-0.1-0.2-0.2-0.2c-0.1-0.1-0.2-0.1-0.3-0.1s-0.2,0-0.4,0h-1.4v1.5H60.8z M60.9,38.2c0.1,0,0.3,0,0.4,0c0.1,0,0.2-0.1,0.3-0.1c0.1-0.1,0.2-0.2,0.2-0.3c0.1-0.1,0.1-0.3,0.1-0.4c0-0.3-0.1-0.6-0.3-0.7c-0.2-0.1-0.4-0.2-0.8-0.2h-1.6v1.8L60.9,38.2L60.9,38.2z M63.7,32.7h1.6l1.6,2.6l1.5-2.6H70l-2.5,4.1v2.5H66v-2.6L63.7,32.7z M87.3,37.7c0.1,0.2,0.2,0.3,0.3,0.4c0.1,0.1,0.3,0.2,0.5,0.2s0.4,0.1,0.6,0.1c0.1,0,0.3,0,0.4,0s0.3-0.1,0.4-0.1c0.1-0.1,0.2-0.1,0.3-0.3c0.1-0.1,0.1-0.2,0.1-0.4s-0.1-0.3-0.2-0.4c-0.1-0.1-0.3-0.2-0.4-0.3c-0.2-0.1-0.4-0.1-0.6-0.2c-0.2-0.1-0.5-0.1-0.7-0.2c-0.2-0.1-0.5-0.1-0.7-0.2c-0.2-0.1-0.4-0.2-0.6-0.3s-0.3-0.3-0.4-0.5C86,35.1,86,34.9,86,34.6c0-0.3,0.1-0.6,0.2-0.9c0.1-0.3,0.3-0.5,0.6-0.6c0.2-0.2,0.5-0.3,0.8-0.4c0.3-0.1,0.6-0.1,0.9-0.1s0.7,0,1,0.1s0.6,0.2,0.8,0.4c0.2,0.2,0.4,0.4,0.6,0.7c0.1,0.3,0.2,0.6,0.2,1h-1.4c0-0.2-0.1-0.4-0.1-0.5c-0.1-0.1-0.2-0.2-0.3-0.3c-0.1-0.1-0.3-0.1-0.4-0.2c-0.2,0-0.3,0-0.5,0c-0.1,0-0.2,0-0.4,0c-0.1,0-0.2,0.1-0.3,0.1c-0.1,0.1-0.2,0.1-0.2,0.2c-0.1,0.1-0.1,0.2-0.1,0.4c0,0.1,0,0.2,0.1,0.3c0,0.1,0.1,0.2,0.3,0.2c0.1,0.1,0.3,0.1,0.6,0.2c0.3,0.1,0.6,0.2,1,0.3c0.1,0,0.3,0.1,0.5,0.1c0.2,0.1,0.4,0.2,0.7,0.3c0.2,0.1,0.4,0.3,0.6,0.6c0.2,0.2,0.2,0.5,0.2,0.9c0,0.3-0.1,0.6-0.2,0.8c-0.1,0.3-0.3,0.5-0.5,0.7s-0.5,0.3-0.9,0.4c-0.3,0.1-0.7,0.2-1.2,0.2c-0.4,0-0.7,0-1.1-0.1c-0.3-0.1-0.6-0.2-0.9-0.4s-0.5-0.4-0.6-0.7c-0.2-0.3-0.2-0.6-0.2-1.1h1.4C87.1,37.4,87.2,37.6,87.3,37.7z M95.5,32.7l2.5,6.6h-1.5L96,37.8h-2.5L93,39.3h-1.5l2.5-6.6H95.5zM95.6,36.8l-0.8-2.4l0,0l-0.9,2.4H95.6z" class="css-1e2dtck"></path><circle fill="transparent" cx="92.3" cy="15.03" r="11.6"></circle><path fill="currentColor" d="M87.078,13.346c0.438-2.931,2.501-4.491,5.065-4.491c3.689,0,5.941,2.682,5.941,6.237c0,3.492-2.376,6.174-6.003,6.174c-2.501,0-4.69-1.497-5.128-4.552h2.939c0.063,1.559,1.126,2.121,2.564,2.121c1.626,0,2.751-1.497,2.751-3.867c0-2.432-0.938-3.742-2.689-3.742c-1.251,0-2.376,0.437-2.626,2.058h0.876l-2.314,2.307l-2.314-2.307L87.078,13.346z M92.269,3.43c-3.189,0-5.941,1.122-8.129,3.368C81.826,9.105,80.7,11.849,80.7,15.03s1.126,5.863,3.439,8.17c2.314,2.245,5.003,3.43,8.129,3.43c3.189,0,5.941-1.123,8.317-3.43c2.189-2.183,3.314-4.864,3.314-8.108s-1.126-5.987-3.377-8.232C98.272,4.491,95.521,3.43,92.269,3.43z M92.269,5.488c2.626,0,4.877,0.936,6.691,2.806c1.876,1.809,2.814,4.054,2.814,6.736c0,2.682-0.938,4.864-2.751,6.611c-1.939,1.871-4.19,2.806-6.754,2.806s-4.815-0.936-6.691-2.806c-1.876-1.871-2.814-4.116-2.814-6.673s0.938-4.802,2.877-6.736C87.391,6.424,89.642,5.488,92.269,5.488z"></path><circle fill="transparent" cx="63.3" cy="15.03" r="11.6"></circle><path fill="currentColor" d="M66.5,12.13c0-0.4-0.3-0.7-0.7-0.7H61c-0.4,0-0.7,0.3-0.7,0.7v4.7h1.3v5.6h3.6v-5.6h1.3V12.13L66.5,12.13z M63.3,7.53c0.9,0,1.6,0.7,1.6,1.6s-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6S62.4,7.53,63.3,7.53z M63.3,3.43c-3.2,0-5.9,1.1-8.2,3.4s-3.4,5.1-3.4,8.2c0,3.2,1.1,5.9,3.4,8.2c2.3,2.3,5,3.4,8.2,3.4s6-1.1,8.3-3.4c2.2-2.2,3.3-4.9,3.3-8.1s-1.1-6-3.4-8.2C69.3,4.53,66.6,3.43,63.3,3.43z M63.4,5.53c2.6,0,4.9,0.9,6.7,2.8c1.9,1.8,2.8,4.1,2.8,6.7c0,2.7-0.9,4.9-2.7,6.6c-1.9,1.9-4.2,2.8-6.8,2.8c-2.6,0-4.8-0.9-6.7-2.8s-2.8-4.1-2.8-6.7s0.9-4.8,2.8-6.7C58.5,6.43,60.7,5.53,63.4,5.53z"></path><circle fill="transparent" cx="21" cy="19" r="15.75"></circle><path fill="currentColor" d="M32.174,7.825c3.08,3.08,4.575,6.775,4.575,11.175s-1.496,8.095-4.487,11.087C29.094,33.254,25.311,34.75,21,34.75s-8.007-1.584-11.086-4.663S5.25,23.311,5.25,19c0-4.311,1.584-8.007,4.663-11.175C12.905,4.746,16.6,3.25,21,3.25S29.182,4.746,32.174,7.825z M11.937,9.849C9.385,12.489,8.066,15.48,8.066,19c0,3.424,1.166,6.349,3.579,8.855c2.237,2.323,5.288,3.778,8.508,3.967c3.874,0.227,7.244-1.092,9.998-3.846c2.464-2.376,3.695-5.367,3.695-9.063c0-3.608-1.232-6.687-3.783-9.151c-2.552-2.552-5.543-3.784-9.151-3.784C17.48,6.066,14.489,7.297,11.937,9.849z M18.8,17.504c-0.352-0.88-0.968-1.32-1.76-1.32c-1.408,0-2.112,0.968-2.112,2.816c0,1.848,0.704,2.816,2.112,2.816c0.88,0,1.584-0.44,1.936-1.408l1.936,1.056c-0.88,1.672-2.288,2.464-4.135,2.464c-1.408,0-2.552-0.44-3.431-1.32s-1.32-2.024-1.32-3.608c0-1.496,0.44-2.728,1.32-3.608s1.936-1.32,3.255-1.32c1.936,0,3.343,0.792,4.135,2.288L18.8,17.504zM27.775,17.504c-0.352-0.88-0.968-1.32-1.76-1.32c-1.408,0-2.112,0.968-2.112,2.816c0,1.848,0.704,2.816,2.112,2.816c0.88,0,1.584-0.44,1.936-1.408l1.936,1.056c-0.88,1.672-2.288,2.464-4.135,2.464c-1.408,0-2.552-0.44-3.431-1.32C21.439,21.728,21,20.584,21,19c0-1.496,0.44-2.728,1.32-3.608s1.936-1.32,3.343-1.32c1.936,0,3.343,0.792,4.135,2.288L27.775,17.504z"></path></svg></a><p class="css-h7w5cw">本作品采用<a title="View license" target="_blank" rel="noopener noreferrer" href="https://creativecommons.org/licenses/by-sa/4.0/" class="css-n2wq6l">《知识共享署名-相同方式共享 4.0 国际许可协议》</a>进行许可</p></section><section class="css-uirvwh"><h3 class="css-1bkjloc">评论</h3><div></div></section></footer></article><aside class="css-1stoowq"><div class="css-1u2ngy8"><h3 class="css-1bkjloc">相关文章</h3><section class="css-1r7n2xc"><small class="css-91fkl8">Lei’s</small><h3 class="css-1wxzomg"><a class="css-n2wq6l" href="/categories/tutorial/">教程</a></h3><svg viewBox="0 0 24 24" width="50" fill="none" stroke="rgba(255, 255, 255, 0.25)" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="margin:0 auto"><path d="M13 14.5s2 3 5 3 5.5-2.463 5.5-5.5S21 6.5 18 6.5c-5 0-7 11-12 11C2.962 17.5.5 15.037.5 12S3 6.5 6 6.5s4.5 3.5 4.5 3.5"></path></svg><ul class="css-19dss5w"><li class="css-no5qqa"><a title="前端工程化 - 脚手架工具" class="css-n2wq6l" href="/2019/08/frontend-engineering-scaffolding/">前端工程化 - 脚手架工具</a></li><li class="css-no5qqa"><a title="Electron 跨平台桌面应用开发" class="css-n2wq6l" href="/2019/08/electron-desktop-app/">Electron 跨平台桌面应用开发</a></li><li class="css-no5qqa"><a title="快速掌握 AJAX - 基础" class="css-n2wq6l" href="/2018/12/ajax-essential/">快速掌握 AJAX - 基础</a></li></ul><footer><a class="css-n2wq6l" href="/categories/tutorial/">查看更多文章 →</a></footer></section><article class="css-1ob3nm1"><a title="POST - Electron 跨平台桌面应用开发" rel="prev" class="css-1jk781r" href="/2019/08/electron-desktop-app/"></a><div class="css-1u6f325 gatsby-image-wrapper" style="position:relative;overflow:hidden"><div aria-hidden="true" style="width:100%;padding-bottom:66.66666666666667%"></div><img aria-hidden="true" src="" alt="Electron 跨平台桌面应用开发" style="position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition-delay:.5s"><noscript><picture><source srcset="/static/d2ab6b0a21a89ed42e17380ee816ed31/c8a29/cover.png 135w, /static/d2ab6b0a21a89ed42e17380ee816ed31/03e09/cover.png 270w, /static/d2ab6b0a21a89ed42e17380ee816ed31/a183f/cover.png 540w, /static/d2ab6b0a21a89ed42e17380ee816ed31/fed18/cover.png 810w, /static/d2ab6b0a21a89ed42e17380ee816ed31/367b3/cover.png 1080w, /static/d2ab6b0a21a89ed42e17380ee816ed31/26ed1/cover.png 1200w" sizes="(max-width: 540px) 100vw, 540px"><img loading="lazy" sizes="(max-width: 540px) 100vw, 540px" srcset="/static/d2ab6b0a21a89ed42e17380ee816ed31/c8a29/cover.png 135w, /static/d2ab6b0a21a89ed42e17380ee816ed31/03e09/cover.png 270w, /static/d2ab6b0a21a89ed42e17380ee816ed31/a183f/cover.png 540w, /static/d2ab6b0a21a89ed42e17380ee816ed31/fed18/cover.png 810w, /static/d2ab6b0a21a89ed42e17380ee816ed31/367b3/cover.png 1080w, /static/d2ab6b0a21a89ed42e17380ee816ed31/26ed1/cover.png 1200w" src="/static/d2ab6b0a21a89ed42e17380ee816ed31/a183f/cover.png" alt="Electron 跨平台桌面应用开发" style="position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center"></picture></noscript></div><div class="css-t1e4o7"><span class="css-1ty11oc">教程</span><h3 class="css-1r5ct1h">Electron 跨平台桌面应用开发</h3><p class="css-1rr4qq7">Electron 是一个运行平台，它能够让我们通过 HTML + CSS + JavaScript 开发桌面应用程序。…</p><footer class="css-1k376o7"><ul class="css-jgo1yj"><li class="css-148vr0x"><a title="汪磊" class="css-n2wq6l" href="/authors/zce/"><img class="css-rr0t5o" alt="汪磊" src="/static/e89ac07ab5eb7c9cf655a5ed73f61806/58a4b/avatar-zce.jpg" srcset="/static/e89ac07ab5eb7c9cf655a5ed73f61806/58a4b/avatar-zce.jpg, /static/e89ac07ab5eb7c9cf655a5ed73f61806/f8771/avatar-zce.jpg 1.5x, /static/e89ac07ab5eb7c9cf655a5ed73f61806/56ed0/avatar-zce.jpg 2x" loading="lazy"></a></li></ul><small>8 分钟</small></footer></div></article><article class="css-1ob3nm1"><a title="POST - 前端工程化 - 脚手架工具" rel="next" class="css-1jk781r" href="/2019/08/frontend-engineering-scaffolding/"></a><div class="css-1u6f325 gatsby-image-wrapper" style="position:relative;overflow:hidden"><div aria-hidden="true" style="width:100%;padding-bottom:66.66666666666667%"></div><img aria-hidden="true" src="" alt="前端工程化 - 脚手架工具" style="position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;object-position:center;opacity:1;transition-delay:.5s"><noscript><picture><source srcset="/static/91b07808be4b7a52f807a1a5d6f03dfb/c8a29/cover.png 135w, /static/91b07808be4b7a52f807a1a5d6f03dfb/03e09/cover.png 270w, /static/91b07808be4b7a52f807a1a5d6f03dfb/a183f/cover.png 540w, /static/91b07808be4b7a52f807a1a5d6f03dfb/fed18/cover.png 810w, /static/91b07808be4b7a52f807a1a5d6f03dfb/85309/cover.png 900w" sizes="(max-width: 540px) 100vw, 540px"><img loading="lazy" sizes="(max-width: 540px) 100vw, 540px" srcset="/static/91b07808be4b7a52f807a1a5d6f03dfb/c8a29/cover.png 135w, /static/91b07808be4b7a52f807a1a5d6f03dfb/03e09/cover.png 270w, /static/91b07808be4b7a52f807a1a5d6f03dfb/a183f/cover.png 540w, /static/91b07808be4b7a52f807a1a5d6f03dfb/fed18/cover.png 810w, /static/91b07808be4b7a52f807a1a5d6f03dfb/85309/cover.png 900w" src="/static/91b07808be4b7a52f807a1a5d6f03dfb/a183f/cover.png" alt="前端工程化 - 脚手架工具" style="position:absolute;top:0;left:0;opacity:1;width:100%;height:100%;object-fit:cover;object-position:center"></picture></noscript></div><div class="css-t1e4o7"><span class="css-1ty11oc">教程</span><h3 class="css-1r5ct1h">前端工程化 - 脚手架工具</h3><p class="css-1rr4qq7">在对前端工程化的整体有了初步的认识之后，我们顺着一个项目的开发过程，先从脚手架开始，探讨前端工程化在项目创建环节中的具…</p><footer class="css-1k376o7"><ul class="css-jgo1yj"><li class="css-148vr0x"><a title="汪磊" class="css-n2wq6l" href="/authors/zce/"><img class="css-rr0t5o" alt="汪磊" src="/static/e89ac07ab5eb7c9cf655a5ed73f61806/58a4b/avatar-zce.jpg" srcset="/static/e89ac07ab5eb7c9cf655a5ed73f61806/58a4b/avatar-zce.jpg, /static/e89ac07ab5eb7c9cf655a5ed73f61806/f8771/avatar-zce.jpg 1.5x, /static/e89ac07ab5eb7c9cf655a5ed73f61806/56ed0/avatar-zce.jpg 2x" loading="lazy"></a></li></ul><small>16 分钟</small></footer></div></article></div></aside></main><footer class="css-1okje3k"><div class="css-1r5spv3"><aside class="css-guslj3"><section class="css-hyqbg3"><h4 class="css-1qmy2f9">社交媒体</h4><p class="css-acwcvw">我们会将最新的、最有意思的内容直接发送到您的收件箱。</p><form class="css-ifr8pt"><input type="email" name="email" placeholder="输入您的邮箱（尚未实现）" autocomplete="off" aria-label="输入您的邮箱" aria-describedby="btn_send" class="css-1suwglb"><button id="btn_send" aria-label="订阅" class="css-15nrm4w"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg></button></form><ul class="css-i8dtig"><li class="css-k4yeou"><a title="推特" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="https://twitter.com/w_zce"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg></a></li><li class="css-k4yeou"><a title="脸书" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="https://www.facebook.com/zccce"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path></svg></a></li><li class="css-k4yeou"><a title="领英" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="https://www.linkedin.com/in/zceme"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg></a></li><li class="css-k4yeou"><a title="GitHub" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="https://github.com/zce"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg></a></li><li class="css-k4yeou"><a title="油管" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="https://www.youtube.com/channel/UCFUwWB0v2qYqLaB95z1nv9Q"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22.54 6.42a2.78 2.78 0 0 0-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.46a2.78 2.78 0 0 0-1.94 2A29 29 0 0 0 1 11.75a29 29 0 0 0 .46 5.33A2.78 2.78 0 0 0 3.4 19c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.78 2.78 0 0 0 1.94-2 29 29 0 0 0 .46-5.25 29 29 0 0 0-.46-5.33z"></path><polygon points="9.75 15.02 15.5 11.75 9.75 8.48 9.75 15.02"></polygon></svg></a></li><li class="css-k4yeou"><a title="微博" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="https://weibo.com/zceme"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg></a></li><li class="css-k4yeou"><a title="微信" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="https://img.zce.me/qrcode/wechat.jpg"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg></a></li><li class="css-k4yeou"><a title="QQ" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="http://wpa.qq.com/msgrd?v=3&amp;uin=27102514&amp;site=qq&amp;menu=yes"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg></a></li><li class="css-k4yeou"><a title="哔哩哔哩" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="https://space.bilibili.com/210242179"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg></a></li><li class="css-k4yeou"><a title="优酷" target="_blank" rel="noopener noreferrer" class="css-1wfhlg8" href="https://i.youku.com/zcezce"><svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg></a></li></ul></section><section class="css-1i892k8"><h4 class="css-1qmy2f9">标签</h4><ul class="css-17lr4dl"><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/untagged/">无标签</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/modular/">Modular</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/es-modules/">ES Modules</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/webpack/">Webpack</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/yeoman/">Yeoman</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/plop/">Plop</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/gulp/">Gulp</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/grunt/">Grunt</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/fis-3/">FIS3</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/npm-scripts/">npm scripts</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/node-js/">Node.js</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/ajax/">AJAX</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/o-auth/">OAuth</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/gatsby/">Gatsby</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/vue-js/">Vue.js</a></li><li class="css-wtmayu"><a class="css-8ro7e7" href="/tags/electron/">Electron</a></li><li class="css-1baulvz"><a class="css-n2wq6l" href="/tags/">更多 →</a></li></ul></section><section class="css-j9xfyi"><h4 class="css-1qmy2f9">链接</h4><ul class="css-owp70s"><li class="css-13pzad3"><a class="css-n2wq6l" href="/story/">故事</a></li><li class="css-13pzad3"><a class="css-n2wq6l" href="/about/">关于我们</a></li><li class="css-13pzad3"><a class="css-n2wq6l" href="/contact/">联系我们</a></li><li class="css-13pzad3"><a class="css-n2wq6l" href="/categories/">全部分类</a></li><li class="css-13pzad3"><a class="css-n2wq6l" href="/archive/">内容归档</a></li><li class="css-13pzad3"><a class="css-n2wq6l" href="/labs/">实验室</a></li></ul></section><section class="css-bonhtd"><h4 class="css-1qmy2f9">订阅</h4><img alt="ITBetter" title="ITBetter" src="https://img.zce.me/qrcode/itbetter.jpg" class="css-16cdh0w"></section></aside><div class="css-kvr7so"><span>© 2020 <a href="https://blog.zce.me" class="css-n2wq6l">Lei’s</a>. 保留所有权利.</span><ul class="css-1lxuut8"><li class="css-go1izf"><a class="css-n2wq6l" href="/privacy-policy/">隐私政策</a></li><li class="css-go1izf"><a class="css-n2wq6l" href="/terms-of-service/">服务条款</a></li></ul><span class="css-1n2mv2k"><a title="查看源代码" target="_blank" rel="noopener noreferrer" class="css-1xwrxje" href="https://github.com/zce/zce.me">&lt;/&gt;</a>with<svg viewBox="0 0 50 50" width="22" height="22"><title>heart</title><g transform="translate(25 25)"><path fill="#fa5252" d="M10.9-20.2c-4.5,0-8.5,2.3-10.9,5.8c-2.4-3.5-6.3-5.8-10.9-5.8c-7.3,0-13.1,5.8-13.1,13C-24,5.7-3.7,11.9,0,20.2C3.7,11.9,24,5.8,24-7.2C24-14.4,18.2-20.2,10.9-20.2"><animateTransform attributeName="transform" calcMode="spline" type="scale" values="0.68;0.8;0.6;0.7200000000000001;0.68;0.6400000000000001" keyTimes="0;0.05;0.39;0.45;0.6;1" keySplines="0.215 0.61,0.355 1;0.215 0.61,0.355 1;0.215 0.61,0.355 1;0.215 0.61,0.355 1;0.215 0.61,0.355 1" dur="1s" repeatCount="indefinite"></animateTransform></path></g></svg>by<a title="由 zce 创作" target="_blank" rel="noopener noreferrer" class="css-wsl0jz" href="https://zce.me">zce</a></span></div></div></footer></div></div><script src="https://hm.baidu.com/hm.js?ebba0e1e4fd2aeae212a8de341d8e1bb"></script><script id="gatsby-script-loader">window.pagePath="/2019/08/frontend-engineering-summary/"</script><script id="gatsby-chunk-mapping">window.___chunkMapping={app:[],"component---node-modules-gatsby-plugin-offline-app-shell-js":[],"component---src-templates-course-js":[],"component---src-templates-page-js":[],"component---src-templates-post-js":[],"component---src-templates-author-js":[],"component---src-templates-category-js":[],"component---src-templates-tag-js":[],"component---src-pages-404-js":[],"component---src-pages-archive-js":[],"component---src-pages-blog-js":[],"component---src-pages-categories-js":[],"component---src-pages-courses-js":[],"component---src-pages-index-js":[],"component---src-pages-labs-js":[],"component---src-pages-tags-js":[]}</script><script src="/aa327c.js" async=""></script><script src="/cdf4f2.js" async=""></script><script src="/d32c95.js" async=""></script><script src="/c89e15.js" async=""></script></body></html>